Run all FeatureExtractors and record results in a key-value format.

        :param feature_extractors: iterable of `FeatureExtractor` objects.

def _generate_features(self, feature_extractors):
        """Run all FeatureExtractors and record results in a key-value format.

        :param feature_extractors: iterable of `FeatureExtractor` objects.
        """
        results = [pd.DataFrame()]
        n_ext = len(feature_extractors)

        for i, extractor in enumerate(feature_extractors):
            log.info("generating: '%s' (%d/%d)", extractor.name, i + 1, n_ext)
            cached_extractor = self._cache[extractor.name]
            if extractor.same(cached_extractor):
                log.info('pulling from cache')
                extractor = cached_extractor
            else:
                log.info('running...')
                extractor.extract()
            results.append(extractor.result)
            if self.cache_path:
                self._cache[extractor.name] = extractor

        if self.cache_path:
            with open(self.cache_path, 'wb') as f:
                pickle.dump(self._cache, f)

        return pd.concat(results, axis=1)