'Iterate over all task keyword arguments in random order.
Randomizing them will help even out the load on the task workers,
though it will not entirely prevent the possibility of spikes.  It will
also make the overall time to completion more predictable.'

def _shuffled_task_kwargs(self, options):

    all_args = []
    estimate_first_attempted = options[u'estimate_first_attempted']
    for course_key in self._get_course_keys(options):
        for task_arg_tuple in tasks._course_task_args(course_key, **options):
            all_args.append(task_arg_tuple)
    all_args.sort(key=(lambda x: hashlib.md5('{!r}'.format(x))))
    for args in all_args:
        (yield {u'course_key': args[0], u'offset': args[1], u'batch_size': args[2], u'estimate_first_attempted': estimate_first_attempted})
