(Nitpicking) I'd write this as ```tuple(type(arg) for arg in args)```
_ has a special meaning in various contexts, and people might be drawing invalid conclusions if they had been working with that other context for a while. Contexts that I know:
In Python's interactive mode, it's a builtin global for the last function result.
As a Python class variable, it would be a private variable.
As a Python function name, it would be the "please translate this string" of the gettext module.
In several declarative programming languages (such as Prolog) it is a variable that cannot be read from, making it valid to write things like (_, _, b) = some_tuple. (x, x, b) = some_tuple would be invalide because the first two elements could be different and further usages of x would be ambiguous. (This one is what threw me off at first.)
In Haskell, _ is a "structural pattern", essentially a don't-care entry when matching the structures of subexpressions.