code: def train(config, env_processes):
    
    tf.reset_default_graph()
    if config.update_every % config.num_agents:
      tf.logging.warn('Number of agents should divide episodes per update.')
    with tf.device('/cpu:0'):
      batch_env = utility.define_batch_env(
          lambda: _create_environment(config),
          config.num_agents, env_processes)
      graph = utility.define_simulation_graph(
          batch_env, config.algorithm, config)
      loop = _define_loop(
          graph, config.logdir,
          config.update_every * config.max_length,
          config.eval_episodes * config.max_length)
      total_steps = int(
          config.steps / config.update_every *
          (config.update_every + config.eval_episodes))
    # Exclude episode related variables since the Python state of environments is
    # not checkpointed and thus new episodes start after resuming.
    saver = utility.define_saver(exclude=(r'.*_temporary.*',))
    sess_config = tf.ConfigProto(allow_soft_placement=True)
    sess_config.gpu_options.allow_growth = True
    with tf.Session(config=sess_config) as sess:
      utility.initialize_variables(sess, saver, config.logdir)
      for score in loop.run(sess, saver, total_steps):
        yield score
    batch_env.close()
docs: Training and evaluation entry point yielding scores.
  
    Resolves some configuration attributes, creates environments, graph, and
    training loop. By default, assigns all operations to the CPU.
  
    Args:
      config: Object providing configurations via attributes.
      env_processes: Whether to step environments in separate processes.
  
    Yields:
      Evaluation scores.