Dereference concatenated variable name

First off, you don't need to use $(echo $FRUITS) in the for statement. Using just $FRUITS is enough. Then you can do away with one of the lines inside the loop, by using eval.

The eval simply tells bash to make a second evaluation of the following statement (i.e. one more than its normal evaluation). The \$ survives the first evaluation as $, and the next evaluation then treats this $ as the start of a variable name, which resolves to "Yellow", etc.

This way you don't need to have a separate step which makes an interim string (which is what I believe was the main intent of your question).

for fruit in $FRUITS ;do
    eval echo $fruit is \$${fruit}_COLOUR
done

For an alternative method, as mentioned by Patrick in a comment (above), you can instead use an associative array, in which an element's index does not need to be an integer. You can use a string, such as the name of a type of fruit. Here is an example, using bash's associative array:

# This declares an associative array (It unsets it if it already exists)
declare -A colour
colour['BANANA']="Yellow"
colour["APPLE"]="Green or Red"
colour[MARTIAN ORANGE]="Blue"

for fruit in BANANA APPLE "MARTIAN ORANGE" ;do 
    echo "$fruit" is "${colour[$fruit]}"
done

You can use the bash-builtin eval to do that:

#!/bin/bash
FRUITS="BANANA APPLE ORANGE"
BANANA_COLOUR="Yellow"
APPLE_COLOUR="Green or Red"
ORANGE_COLOUR="Blue"

for fruit in $( echo $FRUITS );
do
    fruit_colour=${fruit}_COLOUR
    eval echo $fruit is \$${fruit_colour}
done

Note the backslashed-dollar sign. Basically, the "eval" line causes bash to substitue for $fruit and ${fruit_color}, then using eval to do a second round of substition before calling echo.