diff --git a/django/db/models/query.py b/django/db/models/query.py
index 44acadf..ea7c282 100644
--- a/django/db/models/query.py
+++ b/django/db/models/query.py
@@ -3,6 +3,7 @@ The main QuerySet implementation. This provides the public API for the ORM.
 """
 
 import copy
+from collections import namedtuple
 import itertools
 import sys
 
@@ -1056,13 +1057,24 @@ class ValuesQuerySet(QuerySet):
 
 
 class ValuesListQuerySet(ValuesQuerySet):
+    namedtuple_cache = {} # A map of fieldnames -> tuple to use
+    def cached_tuple(self, names):
+        names = tuple(names)
+        try:
+            return self.namedtuple_cache[names]
+        except KeyError:
+            self.namedtuple_cache[names] = namedtuple('ValuesListRow',
+                                                     ' '.join(names))
+            return self.namedtuple_cache[names]
+
     def iterator(self):
         if self.flat and len(self._fields) == 1:
             for row in self.query.get_compiler(self.db).results_iter():
                 yield row[0]
         elif not self.query.extra_select and not self.query.aggregate_select:
+            ret_tuple = self.cached_tuple(self.field_names)
             for row in self.query.get_compiler(self.db).results_iter():
-                yield tuple(row)
+                yield ret_tuple(*row)
         else:
             # When extra(select=...) or an annotation is involved, the extra
             # cols are always at the start of the row, and we need to reorder
@@ -1080,9 +1092,10 @@ class ValuesListQuerySet(ValuesQuerySet):
             else:
                 fields = names
 
+            ret_tuple = self.cached_tuple(fields)
             for row in self.query.get_compiler(self.db).results_iter():
-                data = dict(zip(names, row))
-                yield tuple([data[f] for f in fields])
+                data = dict(zip(names, row))  
+                yield ret_tuple(*[data[k] for k in fields])
 
     def _clone(self, *args, **kwargs):
         clone = super(ValuesListQuerySet, self)._clone(*args, **kwargs)
diff --git a/tests/regressiontests/extra_regress/tests.py b/tests/regressiontests/extra_regress/tests.py
index 67efb42..c2962dc 100644
--- a/tests/regressiontests/extra_regress/tests.py
+++ b/tests/regressiontests/extra_regress/tests.py
@@ -213,22 +213,37 @@ class ExtraRegressTests(TestCase):
 
         # Values list works the same way
         # All columns are returned for an empty values_list()
+        lst = list(TestObject.objects.extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))).values_list())
         self.assertEqual(
-            list(TestObject.objects.extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))).values_list()),
+            lst,
             [(u'first', u'second', u'third', obj.pk, u'first', u'second', u'third')]
         )
+        # Check that the namedtuple names are correctly assigned
+        self.assertEqual(lst[0].foo, u'first')
+        self.assertEqual(lst[0].bar, u'second')
+        self.assertEqual(lst[0].id, obj.pk)
+        self.assertEqual(lst[0].third, u'third')
 
         # Extra columns after an empty values_list() are still included
+        lst = list(TestObject.objects.values_list().extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))))
         self.assertEqual(
-            list(TestObject.objects.values_list().extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third'))))),
+            lst,
             [(u'first', u'second', u'third', obj.pk, u'first', u'second', u'third')]
         )
+        # Check that the namedtuple names are correctly assigned
+        self.assertEqual(lst[0].foo, u'first')
+        self.assertEqual(lst[0].bar, u'second')
+        self.assertEqual(lst[0].id, obj.pk)
+        self.assertEqual(lst[0].third, u'third')
 
         # Extra columns ignored completely if not mentioned in values_list()
+        lst = list(TestObject.objects.extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))).values_list('first', 'second'))
         self.assertEqual(
-            list(TestObject.objects.extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))).values_list('first', 'second')),
-            [(u'first', u'second')]
+            lst, [(u'first', u'second')]
         )
+        # Check that the namedtuple names are correctly assigned
+        self.assertEqual(lst[0].first, u'first')
+        self.assertEqual(lst[0].second, u'second')
 
         # Extra columns after a non-empty values_list() clause are ignored completely
         self.assertEqual(
diff --git a/tests/regressiontests/queries/tests.py b/tests/regressiontests/queries/tests.py
index ded3e8f..03dc9fe 100644
--- a/tests/regressiontests/queries/tests.py
+++ b/tests/regressiontests/queries/tests.py
@@ -1639,6 +1639,12 @@ class ValuesQuerysetTests(BaseQuerysetTest):
             qs, [72]
         )
 
+    def test_values_list_namedtuples(self):
+        Number.objects.create(num=72)
+        qs = Number.objects.values_list("num")
+        self.assertEqual(qs[0][0], 72)
+        self.assertEqual(qs[0].num, 72)
+
 
 class WeirdQuerysetSlicingTests(BaseQuerysetTest):
     def setUp(self):
