### Description

When completing a zero_shot classification task, there is the input sequence (provided by the user), and labels (also provided by the user). 

Tokenization as it is done now tokenizes the input sequence len(labels) times. We should really only do it once and pass those tokenized values to request builder. 

Some of the changes introduce here: https://github.com/elastic/elasticsearch/pull/84777 should make implementing this simpler (as there will be a unified temporary tokenization result object).
x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/inference/nlp/tokenizers/NlpTokenizer.java
abstract int clsTokenId();
    abstract int sepTokenId();
    abstract int maxSequenceLength();
    abstract boolean isWithSpecialTokens();
    abstract int getNumExtraTokensForSeqPair();
    public abstract TokenizationResult buildTokenizationResult(List<TokenizationResult.Tokens> tokenizations);
    /**
     * Tokenize the input according to the basic tokenization
     * options then perform the configured tokenization with the given vocabulary.
     *
     * The result is the tokens ids, a map of the
     * token position to the position of the token in the source for
     * each input string grouped into a {@link Tokenization}.
     *
     * @param seq Text to tokenize
     * @return A list of {@link Tokenization}
     */
    public List<TokenizationResult.Tokens> tokenize(String seq, Tokenization.Truncate truncate, int span, int sequenceId) {
        var innerResult = innerTokenize(seq);
        List<? extends DelimitedToken.Encoded> tokenIds = innerResult.tokens();
        List<Integer> tokenPositionMap = innerResult.tokenPositionMap();
        int numTokens = isWithSpecialTokens() ? tokenIds.size() + 2 : tokenIds.size();
        boolean isTruncated = false;
        if (numTokens > maxSequenceLength()) {
            switch (truncate) {