The discrepancy you're seeing is not related to non-ideal sampling. You are, in fact, sampling ideally. If you plot just the waveform, you'll see that peaks reach 10 as intended; here I've lowered the frequency to 1, to make it easier to see:
f3=1;
Fs=400; % sampling frequency is a bit above 2 times to get all the peaks.
Ts=1/Fs;
Tn=0:Ts:1;
y4_samples=10*sin(2*pi*f3*Tn);
plot(Tn, y4_samples);
Resulting in
Your intention is to take the FFT of this signal to determine the frequency and amplitude. However, there is a problem you're not accounting for. The FFT is designed to work, exactly, on a single cycle signal. While the above plot looks like a single cycle, it has one-too-many samples. If you repeat the array/vector of samples, the last sample in plot is zero, and then you'll start at the beginning—zero again, an unintended repeat, causing a glitch in the waveform. The FFT will see this as "almost" 1 cycle. The error will spill into other frequency "bins"—look up "spectral leakage".
To fix the issue, in this case you can simple lower the number of samples from 401 to 400, by changing the Tn calculation to Tn=0:Ts:1-Ts
(Alternatively, Tn=Ts:Ts:1
to start a sample later), resulting in
Look carefully at the right end of the plot, and you'll see it now stops one sample before it would start the next cycle, allowing an exact cycle loop.
Going back to your original example, and changing just the calculation of Tn:
f3=70;
Fs=400; % sampling frequency is a bit above 2 times to get all the peaks.
Ts=1/Fs;
Tn=0:Ts:1-Ts;
fft_L=length(Tn);
y4_samples=10*sin(2*pi*f3*Tn);
%stem(Tn_new,y4_samples);
ff=fft(y4_samples);
ff1 = abs(ff/fft_L);% normalised FFT
fft2 = ff1(1:floor(fft_L/2)+1); %first half of the vector
fft2(2:end) = 2*fft2(2:end); %we multiply the amplitude by 2
f = Fs*(0:fft_L/2)/fft_L;%frequency vector
plot(f, fft2);
Produces the desired result,
Autoscaling has increased the vertical range, due to slight mathematical inaccuracies, but if you list fft2, you'll see the value is 10, as expected; the first value is 0 Hz, so index 71 corresponds to 70:
>> fft2(71)
ans = 10.000
Again, be aware this will work exactly only for integer number of cycles, so basically 0 to 199 (just under half the sampel rate) in this case. You will see the same spectral leakage you did before if you use 69.5, for instance. Here is the plot for 69.5:
This should make intuitive sense, if you consider that there is no value corresponding to index 70.5 (69.5 + 1) in your fft2 array. The energy from 69.5 is spread between nearby values—the spectral leakage.