//  [python]
def evaluate_fn( lexicon=None, lexicon_prior=None ):
    """Returns a function that evaluates the model for all batches at once or 
    continuously for one batch"""

    def evaluate( features, labels, mode, params ):
                
        logits, sequence_length = _get_image_info( features, mode )

        continuous_eval = params['continuous_eval']
        length = features['length']
            
        # Get the predictions
        batch_loss,\
            batch_label_error,\
            batch_sequence_error, \
            batch_total_labels, \
            _ = _get_testing( logits,sequence_length,labels, length, 
                              continuous_eval, lexicon, lexicon_prior )
        
        # Label errors: mean over the batch and updated total number
        mean_label_error, \
            update_op_label, \
            total_num_label_errors, \
            total_num_labels = _get_label_err_ops( batch_label_error, 
                                                  batch_total_labels )
        
        # Sequence errors: mean over the batch and updated total number
        mean_sequence_error,\
            update_op_seq,\
            total_num_sequence_errs,\
            total_num_sequences = _get_seq_err_ops( batch_sequence_error, 
                                                   length )
        
        # Loss: Accumulated total loss over batches
        total_loss, update_op_loss   = _get_loss_ops( batch_loss )
        mean_loss =  tf.truediv( total_loss, 
                                 tf.cast( total_num_sequences, tf.float32 ),
                                 name='mean_loss' )    
   

        # Print the metrics while doing continuous evaluation (evaluate.py) 
        # Note: tf.Print is identical to tf.identity, except it prints
        # the list of metrics as a side effect
        if (continuous_eval):
            global_step = tf.train.get_or_create_global_step()
            mean_sequence_error = tf.Print( mean_sequence_error, 
                                            [global_step,
                                             batch_loss,
                                             mean_label_error,
                                             mean_sequence_error] ,
                                            first_n=1)
            
            # Create summaries for the metrics during continuous eval
            tf.summary.scalar( 'loss', tensor=batch_loss,
                               family='test' )
            tf.summary.scalar( 'label_error', tensor=mean_label_error,
                               family='test' )
            tf.summary.scalar( 'sequence_error',
                               tensor=mean_sequence_error,
                               family='test' )
            
        # Convert to tensor from Variable in order to pass it to eval_metric_ops
        total_num_label_errors  = tf.convert_to_tensor( total_num_label_errors )
        total_num_labels        = tf.convert_to_tensor( total_num_labels )
        total_num_sequence_errs = tf.convert_to_tensor( total_num_sequence_errs )
        total_num_sequences     = tf.convert_to_tensor( total_num_sequences )
        total_loss              = tf.convert_to_tensor( total_loss )
            
        # All the ops that will be passed to the EstimatorSpec object
        eval_metric_ops = {
            'mean_loss': ( mean_loss, update_op_loss ),
            'mean_label_error': ( mean_label_error, update_op_label ),
            'mean_sequence_error': ( mean_sequence_error, update_op_seq ),
            'total_loss': ( total_loss, tf.no_op() ),
            'total_num_label_errors': ( total_num_label_errors, tf.no_op() ),
            'total_num_labels':( total_num_labels, tf.no_op() ),
            'total_num_sequence_errs': ( total_num_sequence_errs, tf.no_op() ),
            'total_num_sequences': ( total_num_sequences, tf.no_op() ) 
        }
        
        return tf.estimator.EstimatorSpec( mode=mode, 
                                           loss=batch_loss, 
                                           eval_metric_ops=eval_metric_ops )
    return evaluate