def collate(*iterables, **kwargs):
    key = kwargs.pop('key', lambda a: a)
    reverse = kwargs.pop('reverse', False)
    min_or_max = max if reverse else min
    rows = [iter(iterable) for iterable in iterables if iterable]
    next_values = {}
    by_key = []
    def gather_next_value(row, index):
        try:
            next_value = next(row)
        except StopIteration:
            pass
        else:
            next_values[index] = next_value
            by_key.append((key(next_value), index))
    for index, row in enumerate(rows):
        gather_next_value(row, index)
    while by_key:
        key_value, index = min_or_max(by_key)
        by_key.remove((key_value, index))
        next_value = next_values.pop(index)
        yield next_value
        gather_next_value(rows[index], index)