Add optimization for ImmutableList<T>.AddRange

...when adding non-empty range to non-empty list

The AddRange method in ImmutableList<T> currently adds the items in a loop, rebalancing after each add.

This PR will add the entire enumerable in one batch, giving a significant performance improvement

85% improvement when adding an array to to an immutable list
98% improvement when adding an immutable list to an immutable list

My concern is that `MakeBalanced` appears to only be able to tolerate slightly imbalanced trees (it makes at most a small set of rotations). It assumes that the tree is only imbalanced by one operation. But the code you've added can put a tree significantly out of balance, so MakeBalanced would then need enhancement to compensate. 
Whether I'm reading the code wrong or MakeBalanced has to be enhanced, I think we need to see some focused functional tests added to ensure the tree remains balanced after this operation.