I don't like it for 3 reasons:

1. Name. JoinFeatures vs CombinedFeatures is quite confusing. 
2. When used for creating bigram features from unigram features it needs to evaluate each unigram feature function multiple times. 
3. To support ngram features it requires changes to unigram feature functions (e.g. `token_shape` is changed in this PR). This means users can't just combine any existing feature function to get an n-gram feature, they need to modify them to make them useful for JoinFeatures.

This all can be fixed by using "global features" instead of this class: n-gram features implemented as "global features" don't require changes to unigram feature functions, and they reuse results of computations, allowing token-level features to be computed once.