'Run the model through the entire dataset once.
Args:
datasets: A dict of data dicts.  The dataset dict is simply a
name(string)-> data dictionary mapping (See top of lfads.py).
ops_to_eval: A list of tensorflow operations that will be evaluated in
the tf.session.run() call.
batch_size (optional):  The batch_size to use
do_collect (optional): Should the routine collect all session.run
output as a list, and return it?
keep_prob (optional): The dropout keep probability.
Returns:
A list of lists, the internal list is the return for the ops for each
session.run() call.  The outer list collects over the epoch.'

def run_epoch(self, datasets, ops_to_eval, kind='train', batch_size=None, do_collect=True, keep_prob=None):

    hps = self.hps
    all_name_example_idx_pairs = self.shuffle_and_flatten_datasets(datasets, kind)
    kind_data = (kind + '_data')
    kind_ext_input = (kind + '_ext_input')
    total_cost = total_recon_cost = total_kl_cost = 0.0
    session = tf.get_default_session()
    epoch_size = len(all_name_example_idx_pairs)
    evaled_ops_list = []
    for (name, example_idxs) in all_name_example_idx_pairs:
        data_dict = datasets[name]
        data_extxd = data_dict[kind_data]
        if ((hps.output_dist == 'poisson') and (hps.temporal_spike_jitter_width > 0)):
            data_extxd = self.shuffle_spikes_in_time(data_extxd)
        ext_input_extxi = data_dict[kind_ext_input]
        (data_bxtxd, ext_input_bxtxi) = self.get_batch(data_extxd, ext_input_extxi, example_idxs=example_idxs)
        feed_dict = self.build_feed_dict(name, data_bxtxd, ext_input_bxtxi, keep_prob=keep_prob)
        evaled_ops_np = session.run(ops_to_eval, feed_dict=feed_dict)
        if do_collect:
            evaled_ops_list.append(evaled_ops_np)
    return evaled_ops_list
