IMO, any change needs to be both backwards-compatible (i.e., it
should not only "just work", as you phrased, but existing code
should "just keep working"), and forward-compatible, so as not to
obstruct any potential improvements of tuple handling.
Scheme #1 fails backwards-compatibility.
Scheme #2 doesn't, but I feel the matching rules if a type is
specified are too complicated. Instead, I would suggest just to
always assign the variables from the right, i.e. you cannot skip
variables, and if you specify a type, it must match the type of
the value in this position.
If you really want to skip a tuple member (in order to avoid an
expensive copy), a special token "_" or "$" could be introduced,
as has also been suggested in one the tuple unpacking/pattern
matching DIPs, IIRC.
As for unpacking a tuple value (or key), an additional pair of
parentheses can be used, so such a feature would still be
possible in the future:
foreach(i, k, (a,b,c); ...)
(Scheme #3 seems just too complicated for my taste. It's
important to be intuitively understandable and predictable.)