Generator for a list/tuple that potentially contains nested/lists/tuples of arbitrary nesting
    that returns every individual non-list/tuple element.  In other words, [(5, 6, [8, 3]), 2, [2, 1, (3, 4)]]
    will yield 5, 6, 8, 3, 2, 2, 1, 3, 4

    This is safe to call on something not a list/tuple - the original input is yielded.

def flattened_iterator(l, types=(list, tuple)):
    """
    Generator for a list/tuple that potentially contains nested/lists/tuples of arbitrary nesting
    that returns every individual non-list/tuple element.  In other words, [(5, 6, [8, 3]), 2, [2, 1, (3, 4)]]
    will yield 5, 6, 8, 3, 2, 2, 1, 3, 4

    This is safe to call on something not a list/tuple - the original input is yielded.
    """
    if not isinstance(l, types):
        yield l
        return

    for element in l:
        for sub_element in flattened_iterator(element, types):
            yield sub_element