Allow federated_zip intrinsic to take arbitrary structures
Previously, the federated_zip intrinsic only operated on exactly two elements at a time. When users passed structures with more than two elementsto `tff.federated_zip`, a TFF created a tree of calls to the `federated_zip` intrinsic. This resulted in a slightly simpler model for runtime implementations of `federated_zip`, but greatly increased the complexity within the compiler, often resulting in large complex trees of calls with no functional purpose. This CL modifies `federated_zip` and its runtime implementations in order to provide zipping of large, uneven structures through a single call. This results in reduced complexity both in the implementation and in the generate ASTs. PiperOrigin-RevId: 414008706