'Given a course and an iterable of students (User), yield a GradeResult
for every student enrolled in the course.  GradeResult is a named tuple of:
(student, course_grade, err_msg)
If an error occurred, course_grade will be None and err_msg will be an
exception message. If there was no error, err_msg is an empty string.'

def iter(self, users, course=None, collected_block_structure=None, course_key=None, force_update=False):

    course_data = CourseData(user=None, course=course, collected_block_structure=collected_block_structure, course_key=course_key)
    stats_tags = [u'action:{}'.format(course_data.course_key)]
    with self._course_transaction(course_data.course_key):
        for user in users:
            with dog_stats_api.timer('lms.grades.CourseGradeFactory.iter', tags=stats_tags):
                (yield self._iter_grade_result(user, course_data, force_update))
