is there a way to improve this query by not re calculating functions? cross apply?
I beleive you want to store the results of the multiple procs in a single run.
If that's the case then 

I am not sure about what are the columns returned by the procedure sp_count
I am assuming that it returns tablename,total_count

So your code will be like this

USE ORCASTG_CA18_Repl
go
DECLARE @sql VARCHAR(MAX);

CREATE TABLE #table_count (table_name varchar(128), table_count INT)

  SELECT  @sql=COALESCE(@sql+ '', '') 
           + 'INSERT INTO #table exec sp_count ' 
           +'''' + QUOTENAME(OBJECT_SCHEMA_NAME(a.objid)) 
           + '.' + QUOTENAME(a.name) +';'+'''')

FROM dbo.syspublications P 

INNER JOIN dbo.sysarticles A 
        ON P.pubid = A.pubid

INNER JOIN dbo.syssubscriptions s 
        ON a.artid = s.artid 

WHERE 1=1
  AND s.dest_db &lt;&gt; 'virtual'

  EXEC (@sql)

  SELECT * FROM #table_count tc


Also note, I have not tested the code. If you find issues when running please feel free to edit it.

Edit 1:
You can also use  the below methods instead of COALESCE()

STRING_AGG() (2017 onwards)

XML string concatenation

GROUP_CONCAT CLR method (Github)

All these is mentioned in the Aaron bertrand's blog here